import logging
from web.webbase import *
from classes import classes
from imports.n3tagvalue import svalue

def gettag(t):
    return t if t[0].isalpha() else t[1:]

def getprop(t):
    t=gettag(t)
    ns = 'ofx' if t.isupper() else 'a3'
    return ns+':'+t

def getclass(items,typ,acctids,dtstart,dtend,uniqueids,fltrextension=''):
    """Collect objects in items
    typ - the class to be collected as defined in classes module.
    acctids - limit results to lines from ACCTID which is one of the values in the list
    dtstart, dtend - in the class definition look for all the tags that make up the key for an object.
                     if one of those tags begin with DT then it is taken to be the time-key (e.g. DTASOF).
                     take only lines that the time-key falls in the range.
    fltrextension - manually define additional SPARQL filter lines.
    """
    c=classes[typ]
    ms=c['key']+c['mandatory']
    fltr=""
    if acctids and 'ACCTID' not in ms: ms.append('ACCTID')
    if acctids and len(acctids)<10:
        fltr+='filter ('
        fltr+='( ?ACCTID = "'+'" ) || ( ?ACCTID = "'.join(acctids)+'" )'
        fltr+=')\n'
    if dtstart or dtend:
        dtkey=''
        for k in c['key']:
            if k.upper()[0:2]=="DT":
                dtkey=k
                break
    if dtstart and dtkey:
        d,t=svalue(dtkey,list(dtstart)[0])
        fltr+='filter ( ?%s >= "%s"%s )\n'%(dtkey,d,t)
    if dtend and dtkey:
        dtend=list(dtend)[0]
        # make sure dtend refers to the last moment of the day
        if len(dtend)==8 or len(dtend)==6:
            dtend+='235959'
        d,t=svalue(dtkey,dtend)
        fltr+='filter ( ?%s <= "%s"%s )\n'%(dtkey,d,t)
    if uniqueids and 'UNIQUEID' not in ms: ms.append('UNIQUEID')
    if uniqueids and len(uniqueids)<10:
        fltr+='filter ('
        fltr+='( ?UNIQUEID = "'+'" ) || ( ?UNIQUEID = "'.join(uniqueids)+'" )'
        fltr+=')\n'
    fltr+=fltrextension
    os=c['optional']
    vs=ms+os
    #q="""PREFIX ofx:<http://www.w3.org/2000/10/swap/pim/ofx#>
#PREFIX a3:<http://code.google.com/p/3account/wiki/Schema#>
#PREFIX xsd:<http://www.w3.org/2001/XMLSchema#>

    q="""select distinct"""
    for v in vs:
        q+=" ?"+gettag(v)
    q+=" {\n"
    for v in ms:
        q+=" ?x "+getprop(v)+" ?"+gettag(v)+".\n"
    for v in os:
        q+="optional { ?x "+getprop(v)+" ?"+gettag(v)+"}.\n"
    q+=fltr
    q+="}"
    logging.info("SPARQL query:\n%s"%q)
    rows=con.query(q)
    # do post filtering on acctids and uniqueids in case they have more than
    # 10 elements
    # there is no such problem with dtstart/end
    for row in rows:
        if (acctids and
            (row['ACCTID']['value']
             if isinstance(row['ACCTID'],dict)
             else row['ACCTID'][0])
            not in acctids): continue
        if (uniqueids and
            (row['UNIQUEID']['value']
             if isinstance(row['UNIQUEID'],dict)
             else row['UNIQUEID'][0])
            not in uniqueids): continue
        row2dict(items,row,c['key'],vs,typ=typ)
    
def getassets(items,uniqueids):
    if uniqueids:
        getclass(items,'asset',None,None,None,uniqueids)
    for o in items.itervalues():
        if o['type']!='asset': continue
        if 'assetClass' not in o:
            if 'FIASSETCLASS' in o:
                o['assetClass']=o['FIASSETCLASS']                
            elif 'ASSETCLASS' in o:
                o['assetClass']=o['ASSETCLASS']
        if 'SECTYPE' in o:
            nm = o['SECTYPE'][0]+'TYPE'
            if nm in o:
                o['SECTYPE'][0] =o['SECTYPE'][0] + ' ' + o[nm][0]
                
def getassetspercents(items,uniqueids):
    """Find all Asset objects with uniqueids and to each add a 'percent' dictionary which gives
    the percentage of each ASSETCLASS for that asset"""
    getassets(items,uniqueids)
    assetpercents={}
    getclass(assetpercents,'assetpercent',None,None,None,uniqueids)
    for o in assetpercents.itervalues():
        uniqueid=o['UNIQUEID'][0]
        if 'percent' not in items[uniqueid]:
            items[uniqueid]['percent']={}
        items[uniqueid]['percent'][o['ASSETCLASS'][0]]=o['PERCENT'][0]
        
def getpositions(items,acctids,dtstart,dtend,uniqueids=None):
    # Make sure we dont get entries from the same account (ACCTID) from a latter date
    # then the maximal date that falls in the range
    dtend1=list(dtend)[0]
    # make sure dtend refers to the last moment of the day
    if len(dtend1)==8 or len(dtend1)==6:
        dtend1+='235959'
    d,t=svalue('DTASOF',dtend1)
    ext=('optional {'+
            '?y2 ofx:DTASOF ?dt2 . '+
            '?y2 ofx:ACCTID ?ACCTID . '+         
            'filter( ?dt2 > ?DTASOF ).'+
            'filter( ?dt2 <= "%s"%s )'%(d,t)+
        '}. '+
        'filter(!bound(?dt2)).\n')
    getclass(items,'position',acctids,dtstart,dtend,uniqueids,fltrextension=ext)
def gettransactions(items,acctids,dtstart,dtend,uniqueids=None):
    getclass(items,'transaction',acctids,dtstart,dtend,uniqueids)
    getclass(items,'checking',acctids,dtstart,dtend,None)
def getchecking(items,acctids,dtstart,dtend,uniqueids=None):
    getclass(items,'checking',acctids,dtstart,dtend,None)
